
#覆盖型与非覆盖型描述符对比,深刻理解描述符，python属性存取赋值

def cls_name(obj_or_cls):
    cls = type(obj_or_cls)
    if cls is type:
        cls = obj_or_cls
    return cls.__name__.split('.')[-1]
def display(obj):
    cls = type(obj)
    if cls is type:
        return '<class {}>'.format(obj.__name__)
    elif cls in [type(None), int]:
        return repr(obj)
    else:
        return '<{} object>'.format(cls_name(obj))

def print_args(name, *args):
    pseudo_args = ', '.join(display(x) for x in args)
    print('-> {}.__{}__({})'.format(cls_name(args[0]), name, pseudo_args))


class Overriding: 
    """也称数据描述符或强制描述符"""
    def __get__(self, instance, owner):
        print_args('get', self, instance, owner) 
    def __set__(self, instance, value):
        print_args('set', self, instance, value)
    def __delete__(self,inst,name):
        print_args("delete",inst,name)

class OverridingNoGet: 
    """没有``__get__``方法的覆盖型描述符"""
    def __set__(self, instance, value):
        print_args('set', self, instance, value)

class NonOverriding: 
    """也称非数据描述符或遮盖型描述符"""
    def __get__(self, instance, owner):
        print_args('get', self, instance, owner)

class Managed: 
    over = Overriding()
    over_no_get = OverridingNoGet()
    non_over = NonOverriding()
    def spam(self): 
        print('-> Managed.spam({})'.format(display(self)))


manage = Managed()

manage.over 
Managed.over # 通过类属性访问 __set__ 方法里面的 instance 属性会是None

manage.over = 12
print('manage.over,Managed.over 11',manage.over,Managed.over)
Managed.over = 100 #覆盖类属性描述符 实例的也会被覆盖
print('manage.over,Managed.over 22',manage.over,Managed.over)
print('manage.spam=',manage.spam) 
print('Managed.spam=',Managed.spam)
manage.spam = 7
print('manage.spam=',manage.spam,'Managed.spam=',Managed.spam) 

del manage.over

'''

读类属性的操作可以由依附在托管类上定义
的__get__ 方法的描述符处理，但是写类属性的操作不会由依附在托管类上定义的__set__
方法的描述符处理。

'''


class Foo:
    myKey = 1111
    def __init__(self):
        self.name = "Foo"


#描述符会被覆盖 普通属性不会被覆盖
f = Foo()
'''
print('f.myKey',f.myKey)
f.myKey = 100
print('Foo.myKey',Foo.myKey)
Foo.myKey = 200
print('f.myKey',f.myKey,Foo.myKey)
'''